﻿using System;
using System.Collections;
using Castle.DynamicProxy;
using Castle.Windsor;
using ElectronicCommerce.Framework.Ioc.Interceptor;

namespace ElectronicCommerce.Framework.Ioc.Windsor
{
    /// <summary>
    /// Winsor Service Provuder
    /// </summary>
    public class WinsorServiceProvider : IServiceProviderEx
    {

        private readonly IWindsorContainer _container;

        /// <summary>
        /// Winsor Service Provider
        /// </summary>
        /// <param name="container"></param>
        public WinsorServiceProvider(IWindsorContainer container)
        {
            _container = container;

            IntercepterConfigHelper.CreateInercepetors();
        }

        #region IServiceProvider Members

        private object GetService(Type serviceType, IDictionary arguments)
        {
            if (_container.Kernel.HasComponent(serviceType))
            {
                ProxyGenerator generator = new ProxyGenerator();
                var instance =
                    arguments == null
                    ?
                        _container.Resolve(serviceType)
                    :
                        _container.Resolve(serviceType, arguments);
                var intercepters = IntercepterFacator.Creator(serviceType);
                if (intercepters == null || intercepters.Length == 0)
                {
                    return instance;
                }
                return generator.CreateInterfaceProxyWithTargetInterface(serviceType, instance,
                    intercepters);
            }

            return null;
        }

        public object GetService(Type serviceType)
        {
            return GetService(serviceType, null);
        }

        public T GetService<T>()
        {
            return (T)GetService(typeof(T));
        }

        public T GetService<T>(IDictionary arguements)
        {
            return (T)GetService(typeof(T), arguements);
        }

        public T GetService<T>(Type serviceType)
        {
            return (T)GetService(serviceType);
        }

        public void Release(object instance)
        {
            _container.Release(instance);
        }

        #endregion
    }
}
